from django.conf import settings
from django.db import connection, transaction
from django.http import Http404
from rest_framework import exceptions
from rest_framework import mixins
from rest_framework.exceptions import PermissionDenied
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet as GViewSet
from channels.layers import get_channel_layer
from .pagination import PageNumberPaginationExtension
from ..redis import RedisQueue, pool
from redis import Redis


def set_rollback():
    atomic_requests = connection.settings_dict.get('ATOMIC_REQUESTS', False)
    if atomic_requests and connection.in_atomic_block:
        transaction.set_rollback(True)


def exception_handler(exc, context):
    if isinstance(exc, Http404):
        exc = exceptions.NotFound()
    elif isinstance(exc, PermissionDenied):
        return Response({'msg': exc.detail}, status=exc.status_code)

    if isinstance(exc, exceptions.APIException):
        headers = {}
        if getattr(exc, 'auth_header', None):
            headers['WWW-Authenticate'] = exc.auth_header
        if getattr(exc, 'wait', None):
            headers['Retry-After'] = '%d' % exc.wait

        if isinstance(exc.detail, (list, dict)):
            data = exc.detail
        else:
            data = {'detail': exc.detail}

        set_rollback()
        return Response(data, status=exc.status_code, headers=headers)

    return None


class GenericViewSet(GViewSet):
    pagination_class = PageNumberPaginationExtension
    renderer_classes = (JSONRenderer,)

    def __init__(self, *args, **kwargs):
        self.redis = Redis(connection_pool=pool)
        self.layer = get_channel_layer()
        self.namespace = settings.REDIS_NAMESPACE
        self.msg_send_queue = RedisQueue(self.redis, settings.REDIS_BYBASE_SEND_QUEUE_KEY)
        self.known_actions_name = dict()
        super(GenericViewSet, self).__init__(*args, **kwargs)

    def get_params(self):
        """
        ### 将request中的参数提取到一个字典

        :return: 参数字典
        """
        request = self.request
        data = request.data
        results = {}
        if isinstance(data, dict):
            for key in data.keys():
                results[key] = data.get(key, None)
        data_get = {k: v[0] if len(v) == 1 else v for k, v in request.GET.lists()}
        results_get = {}
        if isinstance(data_get, dict):
            for key in data_get.keys():
                results_get[key] = data_get.get(key, None)
        results.update(results_get)
        return results

    def get_client_ip(self):
        x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = self.request.META.get('REMOTE_ADDR')
        return ip


class ModelViewSet(mixins.CreateModelMixin,
                   mixins.ListModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   GenericViewSet):
    pass
